/**
 * 汇编转换模块
 * @module assembler
 */

import { ASSEMBLY_OPCODES, DIRECTION, ERROR_MESSAGES } from './constants.js';

/**
 * 汇编转换器类
 */
class Assembler {
    constructor(turingMachine) {
        this.currentState = 'q0';
        this.nextStateIndex = 1;
        this.tm=turingMachine
    }

    /**
     * 将汇编指令转换为图灵机五元组指令
     * @param {string} assembly 汇编指令
     * @returns {Array} 五元组指令数组
     * @throws {Error} 如果汇编指令无效
     */
    assemble(assembly) {
        const lines = assembly.split('\n').filter(line => line.trim());
        const instructions = [];
        
        for (const line of lines) {
            const instruction = this.parseLine(line.trim());
            if (instruction) {
                instructions.push(...instruction);
            }
        }
        
        return instructions;
    }

    /**
     * 解析单行汇编指令
     * @param {string} line 汇编指令行
     * @returns {Array} 五元组指令数组
     * @throws {Error} 如果汇编指令无效
     */
    parseLine(line) {
        if (!line) return null;
        
        const parts = line.split(/\s+/).filter(part => part);
        const opcode = parts[0].toUpperCase();
        
    // 添加调试输出
    console.log('Parsing line:', line);
    console.log('Current assembler state:', this.currentState);
        switch (opcode) {
            case ASSEMBLY_OPCODES.SET:
                return this.parseSet(parts);
            case ASSEMBLY_OPCODES.MOV:
                return this.parseMove(parts);
            case ASSEMBLY_OPCODES.LOAD:
                return this.parseLoad(parts);
            case ASSEMBLY_OPCODES.STORE:
                return this.parseStore(parts);
            case ASSEMBLY_OPCODES.HALT:
                return [['*', '*', '*', DIRECTION.STAY, 'halt']];
            default:
                throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: ${line}`);
        }
    }

    /**
     * 解析SET指令
     * @param {Array} parts 指令部分数组
     * @returns {Array} 五元组指令数组
     * @throws {Error} 如果指令格式无效
     */
    parseSet(parts) {
        if (parts.length !== 3) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: SET指令需要2个参数`);
        }
        
        const value = this.validateHex(parts[1]);
        const position = parseInt(parts[2]);
        
        if (isNaN(position)) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: 无效的位置`);
        }
        
        // 生成移动和写入指令
        const moveToPosition = this.generateMoveToPosition(position);
        const writeInstruction = [
            this.currentState,
            '*',
            value,
            DIRECTION.STAY,
            `q${this.nextStateIndex++}`
        ];
        
        this.currentState = `q${this.nextStateIndex - 1}`;
        // this.tm.headPosition = position; // 关键：更新探针位置
        return [...moveToPosition, writeInstruction];
    }

    /**
     * 解析MOV指令
     * @param {Array} parts 指令部分数组
     * @returns {Array} 五元组指令数组
     * @throws {Error} 如果指令格式无效
     */
    parseMove(parts) {
        if (parts.length !== 3) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: MOV指令需要2个参数`);
        }
        
        const direction = parts[1].toLowerCase() === 'l' ? DIRECTION.LEFT : parts[1].toLowerCase() === 'r' ? DIRECTION.RIGHT : DIRECTION.STAY;
        const steps = parseInt(parts[2] );
        const stepsAbsolute = Math.abs(steps);
        
        if (isNaN(steps)) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: 无效的步数`);
        }
        
        const instructions = [];
        let remainingSteps = stepsAbsolute;
        const maxStepsPerInstruction = 1; // 每个指令最多移动10步
        
        while (remainingSteps > 0) {
            const currentSteps = Math.min(remainingSteps, maxStepsPerInstruction);
            instructions.push([
                this.currentState,
                '*',
                '*',
                direction,
                `q${this.nextStateIndex++}`
            ]);
            this.currentState = `q${this.nextStateIndex - 1}`;
            remainingSteps -= currentSteps;
        }
        if (remainingSteps === 0 && direction === DIRECTION.STAY) {
            instructions.push([
                this.currentState,
                '*',
                '*',
                DIRECTION.STAY,
                `q${this.nextStateIndex++}`
            ]);
            this.currentState = `q${this.nextStateIndex - 1}`;
        }
        // this.tm.headPosition += steps; // 更新探针位置
        
        return instructions;
    }

    /**
     * 解析LOAD指令
     * @param {Array} parts 指令部分数组
     * @returns {Array} 五元组指令数组
     * @throws {Error} 如果指令格式无效
     */
    parseLoad(parts) {
        if (parts.length < 2 || parts.length > 3) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: LOAD指令需要1-2个参数`);
        }
        
        const position = parseInt(parts[1]);
        const length = parts.length > 2 ? parseInt(parts[2]) : 1;
        
        if (isNaN(position) || isNaN(length)) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: 无效的位置或长度`);
        }
        
        // 生成移动指令
        const moveToPosition = this.generateMoveToPosition(position);
        
        // 生成读取指令 (实际读取操作在图灵机中处理)
        const readInstruction = [
            this.currentState,
            length.toString(16).padStart(2, '0'), // 将长度转为2位十六进制,
            '*',
            DIRECTION.STAY,
            `q${this.nextStateIndex++}`
        ];
        
        this.currentState = `q${this.nextStateIndex - 1}`;
        return [...moveToPosition, readInstruction];
    }

    /**
     * 解析STORE指令
     * @param {Array} parts 指令部分数组
     * @returns {Array} 五元组指令数组
     * @throws {Error} 如果指令格式无效
     */
    /**
     * 解析STORE指令（从缓存写入纸带）
     * 格式：STORE <纸带位置> [缓存位置=0]
     */
    parseStore(parts) {
        if (parts.length !== 2) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: STORE指令需要1个参数`);
        }
        
        const position = parseInt(parts[1]);
        const cachePosition = parts.length > 2 ? parseInt(parts[2]) : 0;
        if (isNaN(position)) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: 无效的位置`);
        }
        
        if (isNaN(cachePosition)) {
            throw new Error(`${ERROR_MESSAGES.INVALID_ASSEMBLY}: 无效的缓存位置`);
        }
        // 生成移动指令
        const moveToPosition = this.generateMoveToPosition(position);
        
        // 生成写入指令 (实际写入操作在图灵机中处理)
        const writeInstruction = [
            this.currentState,
            '*',
            ["c",cachePosition.toString(16).padStart(2, '0')], // 缓存位置转为2位十六进制,
            DIRECTION.STAY,
            `q${this.nextStateIndex++}`
        ];
        
        this.currentState = `q${this.nextStateIndex - 1}`;
        return [...moveToPosition, writeInstruction];
    }

    /**
     * 生成移动到指定位置的指令序列
     * @param {number} targetPosition 目标位置
     * @returns {Array} 五元组指令数组
     */
    generateMoveToPosition(targetPosition,nowPosition=this.tm.headPosition) {
        const instructions = [];
        const steps = targetPosition - (nowPosition + this.currentHeadPosition); // 计算需要移动的步数
        this.currentHeadPosition = steps;
        const direction = steps > 0 ? DIRECTION.RIGHT : steps === 0 ? DIRECTION.STAY : DIRECTION.LEFT;
        
        let remainingSteps = Math.abs(steps);
        const maxStepsPerInstruction = 1; // 每个指令最多移动10步
        
        while (remainingSteps > 0) {
            const currentSteps = Math.min(remainingSteps, maxStepsPerInstruction);
            instructions.push([
                this.currentState,
                '*',
                '*',
                direction,
                `q${this.nextStateIndex++}`
            ]);
            this.currentState = `q${this.nextStateIndex - 1}`;
            remainingSteps -= currentSteps;
        }
        if (remainingSteps===0 && direction===DIRECTION.STAY){
            instructions.push([
                this.currentState,
                '*',
                '*',
                DIRECTION.STAY,
                `q${this.nextStateIndex++}`
            ]);
            this.currentState = `q${this.nextStateIndex - 1}`;
        }
        
        // 更新跟踪的位置
        // this.currentHeadPosition = targetPosition;
        return instructions;
    }

    /**
     * 验证十六进制值
     * @param {string} value 十六进制字符串
     * @returns {string} 标准化后的十六进制值
     * @throws {Error} 如果值无效
     */
    validateHex(value) {
        if (!/^[0-9A-Fa-f]{2}$/.test(value)) {
            throw new Error(`${ERROR_MESSAGES.INVALID_HEX_VALUE}: ${value}`);
        }
        return value.toUpperCase();
    }

    /**
     * 重置汇编器状态
     */
    reset() {
        this.currentState = 'q0';
        this.nextStateIndex = 1;
        this.currentHeadPosition = 0; // 新增：跟踪实时读写头位置
    }
}

export default Assembler;